package com.tju.Util;

/**
 * 日期遍历类，主要用于获取两个时间段之间的每一天
 * Created by Search on 2016/12/6.
 */

import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

public class AccountDate {

    private static transient int gregorianCutoverYear = 1582;

    /**
     * 闰年中每月天数
     */
    private static final int[] DAYS_P_MONTH_LY = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    /**
     * 非闰年中每月天数
     */
    private static final int[] DAYS_P_MONTH_CY = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    /**
     * 代表数组里的年、月、日
     */
    private static final int Y = 0, M = 1, D = 2;

    /**
     * 将代表日期的字符串分割为代表年月日的整形数组
     *
     * @param date
     * @return
     */
    public static int[] splitYMD(String date) {
        date = date.replace("-", "");
        int[] ymd = {0, 0, 0};
        ymd[Y] = Integer.parseInt(date.substring(0, 4));
        ymd[M] = Integer.parseInt(date.substring(4, 6));
        ymd[D] = Integer.parseInt(date.substring(6, 8));
        return ymd;
    }

    /**
     * 检查传入的参数代表的年份是否为闰年
     *
     * @param year
     * @return
     */
    public static boolean isLeapYear(int year) {
        return year >= gregorianCutoverYear ?
                ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0))) : (year % 4 == 0);
    }

    /**
     * 日期加1天
     *
     * @param year
     * @param month
     * @param day
     * @return
     */
    private static int[] addOneDay(int year, int month, int day) {
        if (isLeapYear(year)) {
            day++;
            if (day > DAYS_P_MONTH_LY[month - 1]) {
                month++;
                if (month > 12) {
                    year++;
                    month = 1;
                }
                day = 1;
            }
        } else {
            day++;
            if (day > DAYS_P_MONTH_CY[month - 1]) {
                month++;
                if (month > 12) {
                    year++;
                    month = 1;
                }
                day = 1;
            }
        }
        int[] ymd = {year, month, day};
        return ymd;
    }

    /**
     * 将不足两位的月份或日期补足为两位
     *
     * @param decimal
     * @return
     */
    public static String formatMonthDay(int decimal) {
        DecimalFormat df = new DecimalFormat("00");
        return df.format(decimal);
    }

    /**
     * 将不足四位的年份补足为四位
     *
     * @param decimal
     * @return
     */
    public static String formatYear(int decimal) {
        DecimalFormat df = new DecimalFormat("0000");
        return df.format(decimal);
    }

    /**
     * 计算两个日期之间相隔的天数
     *
     * @param begin
     * @param end
     * @return
     * @throws ParseException
     */
    public static long countDay(String begin, String end) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date beginDate, endDate;
        long day = 0;
        try {
            beginDate = format.parse(begin);
            endDate = format.parse(end);
            day = (endDate.getTime() - beginDate.getTime()) / (24 * 60 * 60 * 1000);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return day;
    }

    /**
     * 以循环的方式计算日期
     *
     * @param beginDate endDate
     * @return
     */
    public static List<String> getEveryday(String beginDate, String endDate) {
        long days = countDay(beginDate, endDate);
        int[] ymd = splitYMD(beginDate);
        List<String> everyDays = new ArrayList<String>();
        everyDays.add(beginDate);
        for (int i = 0; i < days; i++) {
            ymd = addOneDay(ymd[Y], ymd[M], ymd[D]);
            everyDays.add(formatYear(ymd[Y]) + "-" + formatMonthDay(ymd[M]) + "-" + formatMonthDay(ymd[D]));
        }
        return everyDays;
    }

    public static void main(String[] args) {
        System.out.println(getCurHourEnd(new Date()));
        System.out.println(getCurDayStart(new Date()));
        System.out.println(getCurDayEnd(new Date()));
        System.out.println(getCurMonthStart(new Date()));
        System.out.println(getCurMonthEnd(new Date()));
        System.out.println(getCurYearStart(new Date()));
        System.out.println(getCurYearEnd(new Date()));
        System.out.println(getEveryMonth(new Date(), new Date()));
    }

    /**
     * bestwaiting
     * 计算当前天的起点
     *
     * @param time
     * @return ****-**-** 00:00:00
     */
    public static Date getCurDayStart(Date time) {
        Calendar max = Calendar.getInstance();
        max.setTime(time);
        max.set(Calendar.HOUR_OF_DAY, 0);
        max.set(Calendar.MINUTE, 0);
        max.set(Calendar.SECOND, 0);
        max.set(Calendar.MILLISECOND, 0);
        return max.getTime();
    }

    /**
     * bestwaiting
     * 计算当前天的终点
     *
     * @param time
     * @return ****-**-** 23:00:00
     */
    public static Date getCurDayEnd(Date time) {
        Calendar max = Calendar.getInstance();
        max.setTime(time);
        max.set(Calendar.HOUR_OF_DAY, 0);
        max.set(Calendar.MINUTE, 0);
        max.set(Calendar.SECOND, 0);
        max.set(Calendar.MILLISECOND, 0);
        max.add(Calendar.DAY_OF_MONTH, 1);
        max.add(Calendar.HOUR_OF_DAY, -1);
        return max.getTime();
    }

    /**
     * bestwaiting
     * 若当前天没有结束，需要计算当前的时间的前一个小时
     *
     * @param time
     * @return ****-**-** **-1：00：00
     */
    public static Date getCurHourEnd(Date time) {
        Calendar max = Calendar.getInstance();
        max.setTime(time);
        max.set(Calendar.MINUTE, 0);
        max.set(Calendar.SECOND, 0);
        max.set(Calendar.MILLISECOND, 0);
        max.add(Calendar.HOUR_OF_DAY, -1);
        return max.getTime();
    }

    /**
     * bestwaiting
     * 计算当前时间，加10分钟
     *
     * @param time
     * @return ****-**-** **：**+10：00
     */
    public static Date getAddMinute10(Date time) {
        Calendar max = Calendar.getInstance();
        max.setTime(time);
        max.add(Calendar.MINUTE, 10);
        return max.getTime();
    }

    /**
     * bestwaiting
     * 计算当前时间，加一小时
     *
     * @param time
     * @return ****-**-** **+1：00：00
     */
    public static Date getAddHour(Date time) {
        Calendar max = Calendar.getInstance();
        max.setTime(time);
        max.add(Calendar.HOUR, 1);
        return max.getTime();
    }

    /**
     * bestwaiting
     * 计算当前月的起始时间
     *
     * @param time
     * @return ****-**-01 00：00：00
     */
    public static Date getCurMonthStart(Date time) {
        Calendar max = Calendar.getInstance();
        max.setTime(time);
        max.set(Calendar.HOUR_OF_DAY, 0);
        max.set(Calendar.DAY_OF_MONTH, 1);
        max.set(Calendar.MINUTE, 0);
        max.set(Calendar.SECOND, 0);
        max.set(Calendar.MILLISECOND, 0);
        return max.getTime();
    }

    /**
     * bestwaiting
     * 计算当前月的终止时间
     *
     * @param time
     * @return ****-**-28/29/30/31 23：00：00
     */
    public static Date getCurMonthEnd(Date time) {
        Calendar max = Calendar.getInstance();
        max.setTime(time);
        max.set(Calendar.HOUR_OF_DAY, 0);
        max.set(Calendar.DAY_OF_MONTH, 1);
        max.set(Calendar.MINUTE, 0);
        max.set(Calendar.SECOND, 0);
        max.set(Calendar.MILLISECOND, 0);
        max.add(Calendar.MONTH, 1);
        max.add(Calendar.HOUR_OF_DAY, -1);
        return max.getTime();
    }

    /**
     * bestwaiting
     * 计算一年中12个月份
     *
     * @param time
     * @return
     */
    public static List<Date> getMonthInYear(Date time) {
        List<Date> result = new ArrayList<Date>();
        Calendar max = Calendar.getInstance();
        max.setTime(time);
        result.add(max.getTime());
        for (int i = 0; i < 11; i++) {
            max.add(Calendar.MONTH, 1);
            result.add(max.getTime());
        }
        return result;
    }

    /**
     * bestwaiting
     * 计算当前年的起点
     *
     * @param time
     * @return ****-01-01 00：00：00
     */
    public static Date getCurYearStart(Date time) {
        Calendar max = Calendar.getInstance();
        max.setTime(time);
        max.set(Calendar.HOUR_OF_DAY, 0);
        max.set(Calendar.DAY_OF_MONTH, 1);
        max.set(Calendar.MINUTE, 0);
        max.set(Calendar.MONTH, 0);
        max.set(Calendar.SECOND, 0);
        max.set(Calendar.MILLISECOND, 0);
        return max.getTime();
    }

    /**
     * bestwaiting
     * 计算当前年的起点
     *
     * @param time
     * @return ****-12-31 23：00：00
     */
    public static Date getCurYearEnd(Date time) {
        Calendar max = Calendar.getInstance();
        max.setTime(time);
        max.set(Calendar.HOUR_OF_DAY, 0);
        max.set(Calendar.DAY_OF_MONTH, 1);
        max.set(Calendar.MINUTE, 0);
        max.set(Calendar.MONTH, 0);
        max.set(Calendar.SECOND, 0);
        max.set(Calendar.MILLISECOND, 0);
        max.add(Calendar.YEAR, 1);
        max.add(Calendar.HOUR_OF_DAY, -1);
        return max.getTime();
    }

    public static List<Date> getEveryHour(Date date) {
        List<Date> myDate = new ArrayList<Date>();
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        for (int i = 0; i < 24; i++) {
            ca.add(Calendar.HOUR_OF_DAY, 1);
            myDate.add(ca.getTime());
        }
        return myDate;
    }

    public static List<Date> getEveryHourInDay(Date date) {
        List<Date> myDate = new ArrayList<Date>();
        Date nowDate = new Date();
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        while (ca.getTime().compareTo(nowDate) < 0) {
            ca.add(Calendar.HOUR_OF_DAY, 1);
            myDate.add(ca.getTime());
        }
        return myDate;
    }

    /**
     * bestwaiting
     *
     * @param date
     * @param endDate
     * @return 一天中24小时
     */
    public static List<Date> getEveryHourInDay(Date date, Date endDate) {
        List<Date> myDate = new ArrayList<>();
        Date nowDate = new Date();
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        if (cpmDate(nowDate, endDate)) {
            nowDate = getCurHourEnd(nowDate);
        } else {
            if (nowDate.after(endDate)) {
                nowDate = endDate;
            } else {
                nowDate = getCurHourEnd(nowDate);
            }
        }

        while (ca.getTime().compareTo(nowDate) <= 0) {
            myDate.add(ca.getTime());
            ca.add(Calendar.HOUR_OF_DAY, 1);
        }
        return myDate;
    }


    /**
     * copy by xiangyanglai
     * update by bestwaiting 2016/12/26
     *
     * @param date
     * @param endDate
     * @return
     */
    public static List<Date> getEveryHourInDay2(Date date, Date endDate) {
        List<Date> myDate = new ArrayList<Date>();
        Date nowDate = new Date();
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        endDate = getCurDayEnd(endDate);
        if (cpmDate(nowDate, endDate)) {
            nowDate = getCurHourEnd(nowDate);
        } else {
            if (nowDate.after(endDate)) {
                nowDate = endDate;
            } else {
                nowDate = getCurHourEnd(nowDate);
            }
        }
        while (ca.getTime().compareTo(nowDate) <= 0) {
            myDate.add(ca.getTime());
            ca.add(Calendar.HOUR_OF_DAY, 1);
        }
        return myDate;
    }

    /**
     * 比较当前时间是否大于当天23点
     *
     * @param first
     * @param second
     * @return true
     */
    static boolean cpmDate(Date first, Date second) {
        Calendar first1 = Calendar.getInstance();
        first1.setTime(first);
        first1.set(Calendar.MINUTE, 0);
        first1.set(Calendar.SECOND, 0);
        first1.set(Calendar.MILLISECOND, 0);
        Calendar second1 = Calendar.getInstance();
        second1.setTime(second);
        second1.set(Calendar.MINUTE, 0);
        second1.set(Calendar.SECOND, 0);
        second1.set(Calendar.MILLISECOND, 0);
        if (first1.compareTo(second1) == 0)
            return true;
        return false;
    }

    public static Date addOneHour(Date date) {
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        ca.add(Calendar.HOUR_OF_DAY, 1);
        return ca.getTime();
    }

    public static Date addOneMonth(Date date) {
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        ca.add(Calendar.MONTH, 1);
        return ca.getTime();
    }

    public static Date add15Miniutes(Date date) {
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        ca.add(Calendar.MINUTE, 15);
        return ca.getTime();
    }

    public static Date subOneHour(Date date) {
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        ca.add(Calendar.MINUTE, -15);
        return ca.getTime();
    }

    public static Date sub15Miniutes(Date date) {
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        ca.add(Calendar.MINUTE, -15);
        return ca.getTime();
    }

    public static List<Date> getEveryMonth(Date minDate, Date maxDate) {
        List<Date> myDateList = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");//格式化为年月

        Calendar min = Calendar.getInstance();
        Calendar max = Calendar.getInstance();

        min.setTime(minDate);
        min.set(min.get(Calendar.YEAR), min.get(Calendar.MONTH), 1);

        max.setTime(maxDate);
        max.set(max.get(Calendar.YEAR), max.get(Calendar.MONTH), 2);

        Calendar curr = min;
        while (curr.before(max)) {
            myDateList.add(curr.getTime());
            curr.add(Calendar.MONTH, 1);
        }
        return myDateList;
    }

    /**
     * 空调页面查询间隔时间
     *
     * @param date
     * @return
     */
    public static Date subQueryTime(Date date) {
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        ca.add(Calendar.MINUTE, -Constants.QUERY_DEFAULT_AREA_TIME);
        return ca.getTime();
    }


    public static Date addQueryTime(Date date) {
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        ca.add(Calendar.MINUTE, Constants.QUERY_DEFAULT_AREA_TIME);
        return ca.getTime();
    }
}
